/** @format */
interface OriginQuery {
  [key: string]: number | boolean | string | RangeQuery | OriginQuery[] | undefined;
  $where?: any;
  $and?: OriginQuery[];
}

interface RangeQuery {
  $gte?: number | string;
  $gt?: number | string;
  $lt?: number | string;
  $lte?: number | string;
  $in?: (number | string)[];
  $nin?: (number | string)[];
  $eq?: any;
  $neq?: any;
  $exists?: boolean;
  $or?: OriginQuery[];
  $regex?: string;
  $options?: string;
}

interface CommonUpdateOperator {
  $inc?: Record<string, number>;
  $set?: Record<string, any>;
  $push?: Record<string, any>;
  $pull?: Record<string, any>;
  $unset?: Record<string, 1 | true>;
  $addToSet?: Record<string, any>;
  $rename?: Record<string, string>;
}

interface DBCommand {
  gt: (value: number | string) => any;
  gte: (value: number | string) => any;
  lt: (value: number | string) => any;
  lte: (value: number | string) => any;
  in: (value: (number | string)[]) => any;
  nin: (value: (number | string)[]) => any;
  eq: (value: any) => any;
  neq: (value: any) => any;
  exists: (value: boolean) => any;
  or: (value: any[]) => any;
  and: (value: any[]) => any;
}

interface Database {
  command: DBCommand;
}

/**
 * 格式化数据库查询条件（适配 UniCloud JQL）
 * @param db UniCloud 数据库实例
 * @param originQuery 原始查询条件
 * @returns 格式化后的查询条件
 */
export function formatDBQuery(db: Database, originQuery: OriginQuery) {
  const _ = db.command;
  
  // 深拷贝原始查询条件以避免修改原对象
  const clonedQuery: OriginQuery = JSON.parse(JSON.stringify(originQuery));
  clonedQuery.$where && delete clonedQuery.$where;

  // 处理 $and 条件
  if (clonedQuery.$and) {
    clonedQuery.$and.forEach((obj: OriginQuery) => {
      Object.keys(obj).forEach((key: string) => {
        clonedQuery[key] = obj[key];
      });
    });
    delete clonedQuery.$and;
  }

  // 构建查询条件
  const queryConditions = Object.keys(clonedQuery).flatMap((queryKey: string) => {
    const value = clonedQuery[queryKey];
    
    if (value && typeof value === 'object' && !Array.isArray(value)) {
      return Object.keys(value).map((operator: string) => {
        const operatorValue = (value as RangeQuery)[operator as keyof RangeQuery];
        
        // 处理正则表达式
        if (operator === '$regex') {
          const options = (value as any).$options || 'i';
          return {
            [queryKey]: new RegExp(operatorValue as string, options)
          };
        }

        // 处理操作符
        switch (operator) {
          case '$gt': return { [queryKey]: _.gt(operatorValue) };
          case '$gte': return { [queryKey]: _.gte(operatorValue) };
          case '$lt': return { [queryKey]: _.lt(operatorValue) };
          case '$lte': return { [queryKey]: _.lte(operatorValue) };
          case '$in': return { [queryKey]: _.in(operatorValue as (number | string)[]) };
          case '$nin': return { [queryKey]: _.nin(operatorValue as (number | string)[]) };
          case '$eq': return { [queryKey]: _.eq(operatorValue) };
          case '$neq': return { [queryKey]: _.neq(operatorValue) };
          case '$exists': return { [queryKey]: _.exists(operatorValue as boolean) };
          case '$or': return { [queryKey]: _.or(operatorValue as any[]) };
          default: return { [queryKey]: { [operator]: operatorValue } };
        }
      });
    }

    // 简单键值对
    return [{ [queryKey]: value }];
  });

  // 合并所有条件
  return _.and(queryConditions);
}

/**
 * 格式化更新操作符（适配 UniCloud JQL）
 * @param db UniCloud 数据库实例
 * @param updateOperator 原始更新操作符
 * @returns 格式化后的更新操作
 */
export function formatUpdateOperator(db: any, updateOperator: CommonUpdateOperator) {
  const _ = db?.command
  const updateData: Record<string, any> = {}

  // 处理 $set 操作
  if (updateOperator.$set) {
    Object.keys(updateOperator.$set).forEach(key => {
      const setValue = updateOperator.$set?.[key]
      setValue && (updateData[key] = setValue)
    })
  }

  // 处理 $inc 操作
  if (updateOperator.$inc) {
    Object.keys(updateOperator.$inc).forEach(key => {
      const incValue = updateOperator.$inc?.[key]
      incValue && (updateData[key] = _.inc(incValue))
    })
  }

  // 处理 $push 操作
  if (updateOperator.$push) {
    Object.keys(updateOperator.$push).forEach(key => {
      const pushValue = updateOperator.$push?.[key]
      pushValue && (updateData[key] = _.push(pushValue))
    })
  }

  // 处理 $pull 操作
  if (updateOperator.$pull) {
    Object.keys(updateOperator.$pull).forEach(key => {
      const pullValue = updateOperator.$pull?.[key]
      pullValue && (updateData[key] = _.pull(pullValue))
    })
  }

  return updateData
}